# GhostBuddy
This is a DLL to disable brick searching (scope query, for finding bricks to ghost) and to replace it with a script-facing interface to read from pre-populated SimSets containing bricks.

An add-on making use of this DLL can be found here: https://blocklandglass.com/addons/addon.php?id=760

There are also two functions relating to making the brick scope query instantly trigger for a client.
You can have nearby players instantly ghost new bricks when they open a new room in some hypothetical dungeon explorer game.

You can get a visualization of how the game handles brick ghosting by falling down a previously unghosted shaft in one of the mining mods
You will only ghost batches of bricks in distinct intervals of 5 seconds.

## Background
Every 5 seconds, each ShapeBase-derived object attached to a NetConnection (Player and Camera objects) triggers a scope query specifically to search for bricks that need to be ghosted.
With all bricks being stored in the octtree, while much more efficient than the Torque-native system of SceneGraphs still used by non-brick objects,
there is still a non-negligible processing time correlated with brick counts and player counts.
Because the octtree method for bricks is efficient, a server with 1 million bricks out of the ghosting range of 100 players will not have a problem.
However, a server with 100 players and 1 million bricks in ghosting range will have a hard time.
While I have no concrete data on typical values from an actual Blockland server on a VPS, a quick test was setup with the following conditions or assumptions:
	- The New Year's 2024 build has 126,000 bricks almost entirely near the map origin
	- I spawn my player in the middle of the map (in range of almost all 126K bricks)
	- The brick scope query is every 5 seconds per player
	- The brick scope query consumes 11-15 ms for a single player on this specific computer

Therefore, with those circumstances, the server would spend a total of around 1300ms on scope queries every 5 seconds for 100 players, thus resulting in about 25% CPU.

This DLL exposes several several methods to disable the brick scope query and to assist with manually ghosting a list of bricks instead.
A script can collect all bricks on the server into a SimSet and tell the DLL-backed functions that a client needs to start ghosting all bricks in that SimSet.
Any bricks created after the DLL-backed ghosting has finished should be ghosted through script methods to all players as normal ghosting is completely disabled.

## The API (for developers)

Variables
```
$GhostBuddy::brickScopeBlocking
	Inhibit scope queries for bricks
	Internally, this makes octTree::findObjects return zero objects when called during the execution of Player/ShapeBase::onCameraScopeQuery()
	There must be an addon to handle this and manually ghost bricks after this is enabled
$GhostBuddy::totalRadiusSearchTime
	Total time in milliseconds spent on radius searches by every client
	Can be reset to zero as desired
$GhostBuddy::totalRadiusSearchCounter
	Total amount of radius searches done by every client (whether brick scoping was blocked or not)
	Can be reset to zero as desired
```

Variables set on client (GameConnection) objects
```
ghostBuddy_total_radius_search_time
	Total time in milliseconds spent on radius searches by this client
	Can be reset to zero as desired
ghostBuddy_total_radius_search_counter
	Total amount of radius searches done by this client  (whether brick scoping was blocked or not)
	Can be reset to zero as desired
```

Functions
```
GameConnection::ghostBuddy_newClient(group)
	setup the client for ghosting and copy list of objects from the given SimSet

GameConnection::ghostBuddy_clearClient()
	clear data for this client

GameConnection::ghostBuddy_ghostNext(int num)
	ghost next num bricks

GameConnection::ghostBuddy_getIndex()
	get total amount of bricks to be ghosted

GameConnection::ghostBuddy_getCount()
	get number of bricks ghosted so far
```

Functions (for triggering scope queries; not an essential part of this project)
```
GameConnection::ghostBuddy_rescope()
	Immediately make the client query for nearby bricks (brick scope blocking must not be enabled)

GameConnection::ghostBuddy_getSimtimeLastScopeQuery()
	get the simtime of when the last brick scoping query occurred
```


## Installing
Install RedBlocklandLoader (Eagle517) here: https://gitlab.com/Eagle517/redblocklandloader

Create a "modules" folder in your Blockland folder if you don't have one yet.

Copy "GhostBuddy.dll" (located in the release folder of this project) to the "modules" folder.

## Libraries used (for developers)
All dependencies except MinHook are included. This project is setup (USE\_OWN\_MINHOOK) for the MinHook-export version of RedBlocklandLoader which would cause this project to no longer need MinHook for compilation,
however the MinHook-export version of RBL doesn't yet exist at the time of writing.

MinHook - https://notabug.org/Queuenard/blockland-DLL-MinHook (https://github.com/TsudaKageyu/minhook @ 49d03ad118cf7f6768c79a8f187e14b8f2a07f94)

TSfuncs - https://notabug.org/Queuenard/blockland-DLL-libTSfuncs (derived from https://gitlab.com/Eagle517/tsfuncs)

libBLstructs - https://notabug.org/Queuenard/blockland-DLL-libBLstructs

